// import com.alibaba.druid.sql.ast.*;
// import com.alibaba.druid.sql.visitor.SQLASTVisitor;

// import java.util.Collections;
// import java.util.List;

#include "SQLSequenceExpr.h"

#include "../../visitor/SQLASTVisitor.h"
#include "../../../utils/StringUtils.h"
#include "../SQLName.h"

SQLSequenceExpr_Function SQLSequenceExpr_Function::NextVal = SQLSequenceExpr_Function(1 << 0, make_string_ptr("NEXTVAL"));
SQLSequenceExpr_Function SQLSequenceExpr_Function::CurrVal = SQLSequenceExpr_Function(1 << 1, make_string_ptr("CURRVAL"));
SQLSequenceExpr_Function SQLSequenceExpr_Function::PrevVal = SQLSequenceExpr_Function(1 << 2, make_string_ptr("PREVVAL"));

SQLSequenceExpr_Function::SQLSequenceExpr_Function(uint64_t mask, string_ptr name)
{
  this->name = name;
  this->nameLCase = StringUtils::toLower(name);
  this->mask = mask;
}

SQLSequenceExpr_Function::SQLSequenceExpr_Function(SQLSequenceExpr_Function *function)
{
  this->name = function->name;
  this->nameLCase = function->nameLCase;
  this->mask = function->mask;
}

SQLSequenceExpr::SQLSequenceExpr()
{
}

SQLSequenceExpr::SQLSequenceExpr(SQLName_ptr sequence, std::shared_ptr<SQLSequenceExpr_Function> function)
{
  this->sequence = sequence;
  this->function = function;
}

SQLObject_ptr SQLSequenceExpr::clone()
{
  SQLObject_ptr clone_tmp = std::shared_ptr<SQLSequenceExpr>(new SQLSequenceExpr());
  std::shared_ptr<SQLSequenceExpr> x = std::dynamic_pointer_cast<SQLSequenceExpr>(clone_tmp);
  // SQLSequenceExpr x = new SQLSequenceExpr();
  if (sequence != nullptr)
  {
    x->setSequence(std::dynamic_pointer_cast<SQLName>(sequence->clone()));
  }
  x->function = function;
  return x;
}

//@Override
void SQLSequenceExpr::accept0(SQLASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(SQLSequenceExpr)))
  {
    if (this->sequence != nullptr)
    {
      this->sequence->accept(visitor);
    }
  }
  visitor->endVisit(SharedObject(SQLSequenceExpr));
}

//@Override
BOOL_ptr SQLSequenceExpr::replace(SQLExpr_ptr expr, SQLExpr_ptr target)
{
  if (this->sequence == expr)
  {
    setSequence(std::dynamic_pointer_cast<SQLName>(target));
    return BOOL::TRUE;
  }
  return BOOL::FALSE;
}

SQLObject_list_ptr SQLSequenceExpr::getChildren()
{
  SQLObject_list_ptr tmp = SQLObject_list_ptr();
  tmp->push_back(sequence);
  return tmp;
}

SQLName_ptr SQLSequenceExpr::getSequence()
{
  return sequence;
}

void SQLSequenceExpr::setSequence(SQLName_ptr sequence)
{
  this->sequence = sequence;
}

std::shared_ptr<SQLSequenceExpr_Function> SQLSequenceExpr::getFunction()
{
  return function;
}

void SQLSequenceExpr::setFunction(std::shared_ptr<SQLSequenceExpr_Function> function)
{
  this->function = function;
}

//@Override
int SQLSequenceExpr::hashCode()
{
  int prime = 31;
  int result = 1;
  // result = prime * result + ((function == nullptr) ? 0 : function->hashCode());
  result = prime * result + ((function == nullptr) ? 0 : function->mask);
  result = prime * result + ((sequence == nullptr) ? 0 : sequence->hashCode());
  return result;
}

//@Override
bool SQLSequenceExpr::equals(Object_ptr obj)
{
  if (this == obj.get())
  {
    return true;
  }
  if (obj == nullptr)
  {
    return false;
  }
  if (getClass() != obj->getClass())
  {
    return false;
  }
  std::shared_ptr<SQLSequenceExpr> other = std::dynamic_pointer_cast<SQLSequenceExpr>(obj);
  if (function != other->function)
  {
    return false;
  }
  if (sequence == nullptr)
  {
    if (other->sequence != nullptr)
    {
      return false;
    }
  }
  else if (!sequence->equals(other->sequence))
  {
    return false;
  }
  return true;
}
